﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.Collections;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace FUSE
{
    public class DemoMapGenerator : GameComponent
    {
        public const int DEFAULT_NUMBER_COMPONENTS = 2;
        public const String DEFAULT_BACKGROUND = "mapBackground01";
        public const String DEFAULT_TEST_BACKGROUND = "TestBackground";
        public const String DEFAULT_START_PLANET = "startPlanet";
        public const String DEFAULT_END_PLANET = "endPlanet";
        public const String DEFAULT_PLANET = "Planet01Small";

        private static Random randomGenerator;
        private Texture2D mapBackground;
        private Hashtable galaxyComponents;
        private Texture2D componentTexture;

        public StartPlanet startPoint;
        private EndPlanet endPoint;

        public DemoMapGenerator(Game game) 
            : base(game)
        {
            this.startPoint = new StartPlanet();
            this.endPoint = new EndPlanet();

            randomGenerator = new Random();

            this.galaxyComponents = new Hashtable();
        }

        public override void Initialize()
        {
            base.Initialize();

            ContentManager cm = Game.Content;

            this.componentTexture = cm.Load<Texture2D>(DEFAULT_PLANET);
            this.mapBackground = cm.Load<Texture2D>(DEFAULT_BACKGROUND);
            //this.mapBackground = cm.Load<Texture2D>(DEFAULT_TEST_BACKGROUND);


            this.startPoint.Initialize();
            this.startPoint.LoadContent(cm.Load<Texture2D>(DEFAULT_START_PLANET));
            this.startPoint.SetCenterPosition(mapBackground.Width / 2, mapBackground.Height);

            this.endPoint.Initialize();
            this.endPoint.LoadContent(cm.Load<Texture2D>(DEFAULT_END_PLANET));
            this.endPoint.SetCenterPosition(mapBackground.Width / 2, 0);
        }

        public Map GenerateDemoMap(int numberPlanets, int numberSuns) // Will return a Map object
        {
            Map demoMap = new Map(mapBackground.Width, mapBackground.Height);

            demoMap.BackgroundTexture = this.mapBackground;


            GenericForce[,] forces = new GenericForce[mapBackground.Width, mapBackground.Height];
            startPoint.SetCenterPosition(mapBackground.Width / 2, mapBackground.Height);
            endPoint.SetCenterPosition(mapBackground.Width / 2, 0);

            galaxyComponents.Add("StartPlanet", startPoint);
            galaxyComponents.Add("EndPlanet", endPoint);

            for (int index = 0; index < numberSuns; index++)
            {
                Sun sun = new Sun(randomGenerator.Next(10), 10);
                sun.LoadContent(componentTexture);
                Vector2 sunPosition = generatePosition(sun.SlingCircle);

                sun.SetCenterPosition(sunPosition.X, sunPosition.Y);

                galaxyComponents.Add("x" + sunPosition.X + "y" + sunPosition.Y, sun);
            }

            for (int index = 0; index < numberPlanets; index++)
            {
                Planet planet = new Planet(randomGenerator.Next(10), 10);
                planet.LoadContent(componentTexture);
                Vector2 planetPosition = generatePosition(planet.SlingCircle);

                planet.SetCenterPosition(planetPosition.X, planetPosition.Y);
                
                galaxyComponents.Add("x" + planetPosition.X + "y" + planetPosition.Y, planet);
            }

            demoMap.galaxyComponentsTable = galaxyComponents;
            demoMap.galaxyForces = forces;

            return demoMap;
        }

        private Vector2 generatePosition(Circle circle)
        {
            int randomXCoord = randomGenerator.Next((int)circle.radius, (int)(mapBackground.Width - 
                circle.radius));
            int randomYCoord = randomGenerator.Next((int)circle.radius, (int)(mapBackground.Height - 
                circle.radius));

            circle.SetPosition(new Vector2(randomXCoord, randomYCoord));

            Boolean isTooClose = false;
            double distance = 0;

            while (!isTooClose)
            {
         
                foreach (DictionaryEntry item in galaxyComponents)
                {
                    GalaxyComponent value = (GalaxyComponent)item.Value;

                    distance = value.ComponentBounds.DistanceFromCenter(circle);
                    if (value is MassedComponent)
                    {
                        if (distance <= (((MassedComponent)value).SlingCircle.radius + circle.radius))
                        {
                            isTooClose = true;
                            break;
                        }
                    }
                    else
                    {
                        if (distance <= ((((GalaxyComponent)value).ComponentBounds.radius * 2) + circle.radius))
                        {
                            isTooClose = true;
                            break;
                        }
                    }
                }
                if (isTooClose == true)
                {
                    randomXCoord = randomGenerator.Next((int)circle.radius, (int)(mapBackground.Width - 
                        circle.radius));
                    randomYCoord = randomGenerator.Next((int)circle.radius, (int)(mapBackground.Height - 
                        circle.radius));

                    circle.SetPosition(new Vector2(randomXCoord, randomYCoord));

                    isTooClose = false;
                }
                else
                    break;
            }

            return new Vector2(randomXCoord, randomYCoord);
        }
    }
}
